#include "magic.h"
#include <algorithm>
using std::find;

list<Magic *> Magic::m_magics;

/***********  Magic **************/
Magic::Magic()
{
    m_magics.push_back(this);
}

Magic::~Magic()
{
//    cerr << __PRETTY_FUNCTION__ << "\n";
    list<Magic *>::iterator it = std::find(m_magics.begin(), m_magics.end(), this);
    if (it != m_magics.end())
        m_magics.erase(it);
}

void Magic::Draw(BITMAP *surface)
{
    std::for_each(m_magics.begin(), m_magics.end(), std::bind2nd(std::mem_fun(&Magic::draw), surface));
}

/***********  DurationMagic **************/

DurationMagic::DurationMagic(MagicTimer *timer, int interval, int lifetime)
{
    m_valid = true;
    m_timer = timer;
    m_lifetime = lifetime;
    m_timer->add(this, interval);
}

DurationMagic::~DurationMagic()
{
//    cerr << __PRETTY_FUNCTION__ << "\n";
}

/***********  MagicTimer **************/

MagicTimer::~MagicTimer()
{
    MAGIC_LIST::iterator it;
    for (it = m_magics.begin(); it != m_magics.end(); ++it)
    {
        delete (*it).m_magic;
    }
}

void MagicTimer::add(DurationMagic *m, int interval)
{
    m_magics.push_back(MagicStruct(m, interval));
}

void MagicTimer::remove(DurationMagic *m)
{
    MAGIC_LIST::iterator it;
    for (it = m_magics.begin(); it != m_magics.end(); ++it)
    {
        if ((*it).m_magic == m)
        {
            m_magics.erase(it);
            return;
        }
    }
}

void MagicTimer::OnTimer(int tick)
{
    MAGIC_LIST::iterator it;
    for (it = m_magics.begin(); it != m_magics.end(); ++it)
    {
        MagicStruct &ms = *it;
        if (ms.m_magic->valid() && tick - ms.m_lastTick > ms.m_interval)
        {
            ms.m_magic->decLifeTime();
            ms.m_magic->OnTimer();
            ms.m_lastTick = tick;
        }
    }

    for (it = m_magics.begin(); it != m_magics.end(); )
    {
        MagicStruct &ms = *it;
        if (!ms.m_magic->valid())
        {
            delete ms.m_magic;
            m_magics.erase(it++);
        }
        else
        {
            ++it;
        }
    }
}

Missile::~Missile()
{
    if (m_motion)
        delete m_motion;
}

void Missile::OnTimer()
{
    if (m_motion)
        m_motion->move(this);
}
